package org.spring.aop;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.aopalliance.intercept.MethodInterceptor;
import org.spring.aop.framework.ProxyConfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.spring.aop.support.AopUtil.EMPTY_CLASS_ARRAY;

/**
 * AOP 代理配置管理器的基类。
 * 这些本身不是 AOP 代理，但此类的子类通常是工厂，从中可以直接获取 AOP 代理实例。
 *
 * @author 李坤
 * @date 2022/4/18 10:16
 */
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class AdvisedSupport extends ProxyConfig implements Advised {

    /**
     * 被代理对象数据源
     */
    private TargetSource targetSource;

    /**
     * 目标方法通知资格检查类
     */
    private MethodMatcher methodMatcher;

    /**
     * CGLIB 代理对象增强方法回调
     */
    private MethodInterceptor methodInterceptor;

    /**
     * 由代理实现的接口。
     * 保存在 List 中以保持注册顺序，以创建具有指定接口顺序的 JDK 代理。
     */
    private List<Class<?>> interfaces = new ArrayList<>();

    public AdvisedSupport(List<Class<?>> interfaces) {
        this.interfaces = interfaces;
    }

    public AdvisedSupport(TargetSource targetSource, MethodMatcher methodMatcher, MethodInterceptor methodInterceptor) {
        this.targetSource = targetSource;
        this.methodMatcher = methodMatcher;
        this.methodInterceptor = methodInterceptor;
    }

    public void setTargetSource(TargetSource targetSource) {
        this.targetSource = targetSource;

        interfaces.addAll(Arrays.asList(targetSource.getTargetClass().getInterfaces()));
    }

    @Override
    public Class<?> getTargetClass() {
        return targetSource.getTargetClass();
    }

    @Override
    public Class<?>[] getProxiedInterfaces() {
        return interfaces.toArray(EMPTY_CLASS_ARRAY);
    }
}
